package cn.akwangl.concurrency.web.model.order.service.impl;

import cn.akwangl.concurrency.web.exception.BizException;
import cn.akwangl.concurrency.web.model.order.pojo.OrderVo;
import cn.akwangl.concurrency.web.model.order.pojo.SubmitOrderDto;
import cn.akwangl.concurrency.web.model.order.service.CreateOrdersService;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * zookeeper2 curator 框架方式解决线程安全问题.
 *
 * @author 阿坤同学
 * @since 2022-11-22 14:29:53
 */
@Slf4j
@Service("zkCuratorOrdersService")
public class ZkCuratorOrdersServiceImpl implements CreateOrdersService {

    private static final String LOCK_PATH = "/order";

    private CreateOrdersService createOrdersService;

    private CuratorFramework zkClient;

    @Autowired
    @Qualifier("createOrdersService")
    public void setCreateOrdersService(CreateOrdersService createOrdersService) {
        this.createOrdersService = createOrdersService;
    }

    @Autowired
    public void setZkClient(CuratorFramework zkClient) {
        this.zkClient = zkClient;
    }

    @Override
    public OrderVo createOrder(SubmitOrderDto submitOrderDto) {
        InterProcessMutex lock = new InterProcessMutex(zkClient, LOCK_PATH);
        try {
            if (lock.acquire(5, TimeUnit.SECONDS)) {
                try {
                    return createOrdersService.createOrder(submitOrderDto);
                } finally {
                    lock.release();
                }
            }
            return null;
        } catch (Exception e) {
            log.error("ZK 获取锁失败", e);
            throw new BizException("下单失败");
        }
    }
}
